package com.qianxun.plugins.log;

import lombok.extern.slf4j.Slf4j;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Arrays;

/**
 * 日志记录对象
 * @author: huwei
 * @date: 2019/10/17 13:42
 * @version: 1.0.0
 */
@Slf4j
public class Logger {

    /**
     * 前置log记录，该记录在目标方法执行之前调用
     * @param logInfo log信息
     */
    public void beforeLog(LogInfo logInfo){
        StringBuffer stringBuffer = new StringBuffer("\r\n");
        stringBuffer.append("方法执行开始：").append(logInfo.getMethodSignature()).append("\r\n");
        stringBuffer.append("方法所属类：").append(logInfo.getClassName()).append("\r\n");
        if(!"".equals(logInfo.getTitle()) || !"".equals(logInfo.getLogPoint().value())) {
            stringBuffer.append("方法标题：").append(logInfo.getTitle()).append(".").append(logInfo.getLogPoint().value()).append("\r\n");
        }
        if(!"".equals(logInfo.getKey())){
            stringBuffer.append("方法key值：").append(logInfo.getKey()).append("\r\n");
        }
        if(!"".equals(logInfo.getNotes())){
            stringBuffer.append("方法描述：").append(logInfo.getNotes()).append("\r\n");
        }
        if(logInfo.getSign().length != 0){
            stringBuffer.append("方法标签：").append(Arrays.toString(logInfo.getSign())).append("\r\n");
        }
        if(logInfo.getParameterMap().isEmpty()) {
            stringBuffer.append("方法参数：").append(logInfo.getParameterArray()).append("\r\n");
        }else{
            stringBuffer.append("方法参数：").append(logInfo.getParameterMap()).append("\r\n");
        }
        log.info(stringBuffer.toString());
    }

    /**
     * 异常log记录，该记录将在目标方法执行抛出异常时调用
     * @param logInfo log信息
     */
    public void errorLog(LogInfo logInfo){
        StringBuffer stringBuffer = new StringBuffer("\r\n");
        stringBuffer.append("方法执行异常：").append(logInfo.getMethodSignature()).append("\r\n");
        if(!"".equals(logInfo.getKey())){
            stringBuffer.append("方法key值：").append(logInfo.getKey()).append("\r\n");
        }

        stringBuffer.append("异常信息堆栈: ").append(getErrorStackMessage(logInfo.getCause())).append("\r\n");
        log.info(stringBuffer.toString());
    }

    /**
     * 后置log记录，该记录在目标方法执行之后且不管成功或失败调用
     * @param logInfo log信息
     */
    public void afterLog(LogInfo logInfo){
        StringBuffer stringBuffer = new StringBuffer("\r\n");
        stringBuffer.append("方法执行完毕：").append(logInfo.getMethodSignature()).append("\r\n");
        if(!"".equals(logInfo.getKey())){
            stringBuffer.append("方法key值：").append(logInfo.getKey()).append("\r\n");
        }
        if(logInfo.getLogPoint().isRecordResult()){
            if(logInfo.getResult() == null){
                stringBuffer.append("方法执行结果：NULL").append("\r\n");
            }else {
                int maxLength = logInfo.getLogPoint().maxLengthForResult();
                String resultStr = logInfo.getResult().toString();
                String result = maxLength == -1 || resultStr.length() < maxLength ? resultStr : resultStr.substring(0 ,maxLength).concat("...") ;
                stringBuffer.append("方法执行结果：").append(result).append("\r\n");
            }
        }
        log.info(stringBuffer.toString());
    }

    private String getErrorStackMessage(Throwable cause){
        ByteArrayOutputStream baos = new ByteArrayOutputStream(1024);
        cause.printStackTrace(new PrintWriter(baos));
        String result = baos.toString();
        try {
            baos.close();
        } catch (IOException e) {
            //ignore
        }
        return result;
    }
}
